#ifndef FOUNDATION_DATA_ACQ_CHANNELTASK_H
#define FOUNDATION_DATA_ACQ_CHANNELTASK_H
#include "dbms_channel.h"
#include "dbms_device.h"
#include <vendor_global.h>
#include <string>
#include <functional>
#include <thread>
#include <vector>
#include <queue>
#include <mutex>
#include "device_task.h"

namespace data_acq {
struct AcqInfo {
	std::weak_ptr<DeviceTask> device;
	std::vector<dbms::Funcpoint_t> funcPoints;
	std::vector<libxcom::OpValue> params;
	SubscribeCallback subsribeFunc;
	SubscribeExceptionCallback subsribeExceptionFunc;
};

class ChannelTask {
public:
	ChannelTask(const dbms::DeviceChannel_t &channel);
	~ChannelTask();
	int32_t ID();
	bool HasDevice(const std::string &deviceId);

	void Subscribe(SubscribeCallback subscrib);
	void SubscribeException(SubscribeExceptionCallback subscribe);
	void Start(bool detach = true);
	void Stop();
	bool IsRunning() const;
	void Run();
	void DoAcq();

	bool PopQueue(AcqInfo &acq);
	void PushQueue(const AcqInfo &acqInfo);
	void CommitImmedAcq(const std::string &deviceId,
		const std::vector<dbms::AcqItem_t> &items,
		SubscribeCallback subsribeFunc = nullptr,
		SubscribeExceptionCallback subsribeExceptionFunc = nullptr);
	std::vector<uint8_t> DownlinkWork(const std::vector<uint8_t> &cmd);

protected:
	virtual void OnPeriodTimeout();
	virtual void OnGetPeriodAcq();
	virtual bool OnDownlink(
		const libxcom::CmdValue &recv, const ParseRecv &parseRecv);
	virtual void OnGetDevices(
		std::vector<std::shared_ptr<DeviceTask> > &deviceTaskList);
	void OnPeriodUpdate();

private:
	dbms::DeviceChannel_t deviceChannel_;
	SubscribeCallback subsribeFunc_ = nullptr;
	SubscribeExceptionCallback subsribeExceptionFunc_ = nullptr;
	std::thread threadTask_;
	uv_loop_t *uvLoop_ = nullptr;
	uv_async_t uvAsync_;
	uv_timer_t uvTimer_;
	uv_async_t uvImmed_;
	uv_timer_t uvTimerUp_;
	std::atomic<bool> run_{false};
	std::vector<std::shared_ptr<DeviceTask> > deviceTaskList_;
	std::shared_ptr<downlink::DownlinkConnect> downlink_;

	std::mutex queueMutex_;
	std::queue<AcqInfo> deviceTaskQueue_;
};
} // namespace data_acq
#endif